Portfolio Process API (PAPI) v1.3.0
Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.
A Process API (PAPI) responsible for orchestrating, transforming, and filtering data from the Salesforce System API (SAPI) for consumption by the Portfolio frontend.
1. Authentication Strategy
- Frontend → PAPI: Uses MuleSoft/Salesforce Client Credentials (
client_id,client_secret) in headers. - PAPI → SAPI: Uses separate internal Client Credentials stored in
configuration.yaml(or AWS Secrets Manager).
2. Versioning Strategy
- Pattern: Header-based versioning takes precedence.
- Header:
X-API-Version: v1(Required). - URL: Version segments removed from base path to align with SAPI ADR.
3. Rate Limiting & Aggregation Math
- SAPI Limit: 120 requests/minute.
- PAPI Aggregation: A single
/profile/fullcall triggers ~8 upstream SAPI calls. - PAPI Limit: Restricted to 15 requests/minute (Standard Tier) to prevent cascading rate limit violations on SAPI (15 * 8 = 120).
4. Caching Strategy (Aggregation Logic)
Note: PAPI cannot pass SAPI headers verbatim due to mixed sensitivity in aggregated payloads.
- Rule: Strictest policy wins.
- If any upstream resource is
no-store(e.g., Contact) → PAPI response isno-store. - If any upstream resource is
private→ PAPI response isprivate. - Otherwise → PAPI response is
publicwith the minimummax-age.
- If any upstream resource is
5. Field Mapping (Transformation Layer)
| Object | SAPI Field | PAPI Field | Logic |
| :— | :— | :— | :— |
| Contact | name | fullName | Rename |
| Experience | name | role | Semantic Rename |
| Certification | earnedDate | dateEarned | JS Convention |
| Project | dateCompleted | completionDate | JS Convention |
| Project | heroImageUrl | heroImageUrl | Passthrough |
Base URLs:
Email: Ryan Bumstead Web: Ryan Bumstead License: MIT
Authentication
- API Key (ClientIdAuth)
- Parameter Name: client_id, in: header. MuleSoft/Salesforce Client ID
- API Key (ClientSecretAuth)
- Parameter Name: client_secret, in: header. MuleSoft/Salesforce Client Secret (Standard Enforcement Policy)
Orchestration
Endpoints that aggregate multiple SAPI calls
getFullPortfolio
Code samples
const headers = {
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/profile/full',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /profile/full
Get Complete Portfolio State
The “Hydration” endpoint. Returns the entire portfolio state in a single call.
Parallel Execution Strategy: The following groups are executed in parallel:
- Config Group:
/portfolio-config,/contacts - Work History Group:
/experience,/education,/certifications - Portfolio Group:
/projects,/skills,/testimonials
Note: Junction object calls (e.g., /project-skills) are dependent on their parent calls and execute sequentially within their group.
Architecture Strategies:
- Recursive Pagination: Consumes
X-Has-Morefrom SAPI to fetch all pages. - Partial Failure Tolerance: “Best Effort” aggregation.
- Timeout: 3 seconds per group.
- If a group fails, the main response returns
200 OKwith empty arrays for that section andX-Data-Integrity: partial.
- Smart Caching: Applies strictest upstream cache policy.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
Example responses
200 Response
{
"config": {
"ownerEmail": "bumsteadryan@gmail.com",
"ownerPhone": "+1 555-0199",
"linkedInUrl": "https://linkedin.com/in/ryanbumstead",
"calendlyUrl": "https://calendly.com/ryanbumstead",
"githubUrl": "https://github.com/ryanbumstead",
"trailheadUrl": "https://trailblazer.me/id/ryanbumstead",
"personalWebsiteUrl": "https://ryanbumstead.com",
"careerObjective": "Driving digital transformation through architecture."
},
"contactInfo": {
"id": "0035e00000B2O3DAAV",
"fullName": "Ryan Bumstead",
"email": "bumsteadryan@gmail.com",
"phone": "555-0199",
"title": "Platform Architect",
"linkedIn": "https://linkedin.com/in/ryanbumstead",
"github": "https://github.com/ryanbumstead",
"trailhead": "https://trailblazer.me/id/ryanbumstead",
"portfolioUrl": "https://ryanbumstead.com",
"bio": "Specializing in API-led connectivity..."
},
"summary": "7+ Years of Experience as a Salesforce Platform Architect specializing in API-led connectivity and DevOps.",
"skills": [
{
"id": "a075e00000B2O3DAAV",
"name": "Apex",
"displayName": "Salesforce Apex",
"category": "Backend",
"proficiency": 5,
"iconName": "utility:code",
"colorHex": "#0070d2"
},
{
"id": "a075e00000B2O3DAAX",
"name": "LWC",
"displayName": "Lightning Web Components",
"category": "Frontend",
"proficiency": 5,
"iconName": "standard:lightning_component",
"colorHex": "#00A1E0"
}
],
"experience": [
{
"id": "a025e00000B2O3DAAV",
"employer": "Salesforce",
"role": "Senior Technical Architect",
"dateRange": "Jan 2023 - Present",
"isCurrent": true,
"isRemote": true,
"skillsUsed": [
"Apex",
"LWC",
"Event Bus"
],
"highlights": [
"Designed multi-cloud architectures",
"Led DevOps transformation"
]
}
],
"projects": [
{
"id": "a015e00000B2O3DAAV",
"title": "Portfolio Site",
"challenge": "Display skills dynamically",
"solution": "Built on LWR with SAPI/PAPI architecture",
"businessValue": "Increased interview rate by 40%",
"status": "Live – In Production",
"completionDate": "2025-12-01",
"heroImageUrl": "https://assets.portfolio.com/hero.png",
"liveUrl": "https://portfolio.ryanbumstead.com",
"repositoryUrl": "https://github.com/ryanbumstead/portfolio",
"technologies": [
"LWR",
"Apex"
],
"assets": []
}
],
"certifications": [
{
"id": "a105e00000B2O3DAAV",
"name": "Certified Application Architect",
"issuer": "Salesforce",
"dateEarned": "2024-05-15",
"skillsUsed": [
"Security"
]
}
],
"education": [
{
"id": "a115e00000B2O3DAAV",
"school": "Creighton University",
"degree": "B.S. Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2018",
"gpa": 3.8
}
],
"testimonials": [
{
"id": "a055e00000B2O3DAAV",
"author": "Jane Doe",
"title": "VP of Engineering",
"relationship": "Manager",
"quote": "Ryan is a beast at architecture.",
"vibe": "Professional",
"avatarUrl": "https://linkedin.com/in/janedoe/photo"
}
],
"integrityNote": "Complete"
}
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | The complete portfolio payload | FullPortfolioPayload |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | Cache-Control | string | Derived from upstream SAPI resources (Contacts = no-store). | |
| 200 | X-Data-Integrity | string | Indicates if the payload is complete or has partial missing data. | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
getProfileSummary
Code samples
const headers = {
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/profile/summary',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /profile/summary
Get Employment Profile Only
Orchestrates calls to Contact, Work Experience, Skills, Education, and Certifications. Stitches junction objects (ExperienceSkill, CertificationSkill) to their parents.
SAPI Calls:
GET /contactsGET /experience→GET /experience-skills?experienceId={id}for eachGET /skillsGET /certifications→GET /certification-skills?certificationId={id}for eachGET /education
Use Case: Resume page, profile cards
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
Example responses
200 Response
{
"contactInfo": {
"id": "0035e00000B2O3DAAV",
"fullName": "Ryan Bumstead",
"email": "ryan@ryanbumstead.com",
"phone": "+1 555-0199",
"title": "Platform Architect",
"linkedIn": "https://linkedin.com/in/ryanbumstead",
"github": "https://github.com/ryanbumstead",
"trailhead": "https://trailblazer.me/id/ryanbumstead",
"portfolioUrl": "https://ryanbumstead.com",
"bio": "Specializing in API-led connectivity..."
},
"summary": "7+ years of experience as a Salesforce Platform Architect",
"skills": [
{
"id": "a075e00000B2O3DAAV",
"name": "Apex",
"displayName": "Salesforce Apex",
"category": "Backend",
"proficiency": 5,
"iconName": "utility:code",
"colorHex": "#0070d2",
"categoryOrder": 10
}
],
"experience": [
{
"id": "a025e00000B2O3DAAV",
"employer": "Salesforce",
"role": "Senior Technical Architect",
"dateRange": "Jan 2023 - Present",
"isCurrent": true,
"isRemote": true,
"skillsUsed": [
"LWC"
],
"highlights": [
"Implemented CI/CD pipelines using GitHub Actions"
]
}
],
"certifications": [
{
"id": "a105e00000B2O3DAAV",
"name": "Certified Application Architect",
"issuer": "Salesforce",
"dateEarned": "2024-05-15",
"skillsUsed": [
"Security"
]
}
],
"education": [
{
"id": "a115e00000B2O3DAAV",
"school": "Creighton University",
"degree": "B.S. Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2018",
"gpa": 3.8
}
]
}
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | A unified profile object | ProfileSummary |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | Cache-Control | string | none | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
getFeaturedProjects
Code samples
const headers = {
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/projects/featured',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /projects/featured
Get Featured Projects (Enriched)
Retrieves projects marked as ‘Featured’ with nested Skills and Assets.
SAPI Calls:
GET /projects?isFeatured=true- For each project:
GET /project-skills?projectId={id}GET /project-assets?projectId={id}
Use Case: Home page project showcase, portfolio gallery
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
Example responses
200 Response
[
{
"id": "a015e00000B2O3DAAV",
"title": "Portfolio Site",
"challenge": "Display skills dynamically to recruiters",
"solution": "Built on LWR with SAPI/PAPI architecture",
"businessValue": "Increased interview rate by 40%",
"status": "Live – In Production",
"completionDate": "2025-12-01",
"heroImageUrl": "https://assets.portfolio.com/hero.png",
"liveUrl": "https://portfolio.ryanbumstead.com",
"repositoryUrl": "https://github.com/ryanbumstead/portfolio",
"technologies": [
"Apex"
],
"pillarLabel": "Pillar A: Business Architecture",
"assets": [
{
"type": "Image",
"url": "https://assets.portfolio.com/diagram.png",
"caption": "System Architecture Diagram"
}
]
}
]
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | A list of enriched project records | Inline |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| anonymous | [EnrichedProject] | false | none | [Project enriched with Skills and Assets] |
| » id | string | true | none | none |
| » title | string¦null | false | none | none |
| » challenge | string | false | none | none |
| » solution | string | false | none | none |
| » businessValue | string | false | none | none |
| » status | string¦null | false | none | Project Status (e.g., Live, Archived) |
| » completionDate | string(date)¦null | false | none | Mapped from SAPI dateCompleted |
| » heroImageUrl | string(uri) | false | none | URL of the main display image. Matches SAPI field name. |
| » liveUrl | string(uri) | false | none | none |
| » repositoryUrl | string(uri) | false | none | none |
| » technologies | [string] | false | none | Skill names from ProjectSkill junction |
| » pillarLabel | string¦null | false | none | The strategic pillar and pillar description (e.g. Pillar A: Business Architecture) |
| » assets | [object] | false | none | Images, videos, or links related to the project |
| »» type | string | true | none | none |
| »» url | string(uri) | true | none | none |
| »» caption | string | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| type | Image |
| type | Video |
| type | Document |
| type | Link |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | X-Total-Count | integer | none | |
| 200 | Cache-Control | string | none | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
Transformation
Endpoints that transform SAPI data into new formats
generateResume
Code samples
const headers = {
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/resume/generate',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /resume/generate
Generate Plain Text Resume
Generates an ATS-optimized plain text resume.
SAPI Calls:
GET /contactsGET /experienceGET /experience-highlights?persona={persona}- Filters bullets by target audienceGET /skillsGET /certificationsGET /education
Transformation Logic:
- Formats dates as “MMM YYYY - MMM YYYY” or “MMM YYYY - Present”
- Groups skills by category
- Limits to top 5 proficiency skills per category
- Strips HTML from accomplishments using regex
- Applies 80-character line wrapping
Persona Filtering:
Admin: System Admin highlights onlyDeveloper: Development highlights onlyArchitect: Architecture/Design highlights only
SAPI Mapping:
- PAPI persona values are passed directly to SAPI
/experience-highlights?persona={value} - If persona is omitted, all highlights are returned (no filtering)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
| persona | query | string | false | Target audience for the resume. Omit for all highlights. |
Detailed descriptions
persona: Target audience for the resume. Omit for all highlights.
Note: This value is passed directly to SAPI’s persona filter.
Enumerated Values
| Parameter | Value |
|---|---|
| persona | Admin |
| persona | Developer |
| persona | Architect |
Example responses
200 Response
{
"generatedText": "Ryan Bumstead\nSalesforce Platform Architect\n\nEXPERIENCE\n\nSalesforce | Senior Technical Architect\nJan 2023 - Present\n- Designed multi-cloud solutions...\n- Led DevOps transformation...\n",
"persona": "Architect",
"generatedAt": "2019-08-24T14:15:22Z"
}
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | A JSON object containing the formatted resume text | Inline |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| » generatedText | string | true | none | The complete, formatted resume string ready for clipboard copy |
| » persona | string | true | none | The persona filter applied |
| » generatedAt | string(date-time) | true | none | ISO 8601 timestamp of generation |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | Cache-Control | string | none | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
Logic
Endpoints that apply business rules and filtering
getTestimonialFeed
Code samples
const headers = {
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/testimonials/feed',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /testimonials/feed
Get Curated Testimonials
Retrieves testimonials with “Vibe Control” logic applied.
SAPI Calls:
GET /testimonials?limit=200(returns onlyApproved__c = true)
Filtering Logic:
professional: Filters result set to only include records whererelationshipIN (‘Manager’, ‘Client’, ‘Peer’) ANDvibe= ‘Professional’.casual: Returns all approved testimonials, regardless of relationship type or vibe (includes ‘Casual’ vibe and ‘Fan’ relationships).
Use Case: About page testimonials section
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
| mode | query | string | false | Filter testimonials by vibe |
Enumerated Values
| Parameter | Value |
|---|---|
| mode | professional |
| mode | casual |
Example responses
200 Response
[
{
"id": "a055e00000B2O3DAAV",
"author": "Jane Doe",
"title": "VP of Engineering",
"relationship": "Manager",
"quote": "Ryan is a beast at architecture",
"vibe": "Professional",
"avatarUrl": "https://linkedin.com/in/janedoe/photo"
}
]
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | A filtered list of testimonials | Inline |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| anonymous | [EnrichedTestimonial] | false | none | none |
| » id | string | true | none | none |
| » author | string | true | none | none |
| » title | string | false | none | none |
| » relationship | string | false | none | none |
| » quote | string | true | none | none |
| » vibe | string | false | none | none |
| » avatarUrl | string(uri) | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| relationship | Manager |
| relationship | Peer |
| relationship | Client |
| relationship | Recruiter |
| relationship | Fan |
| vibe | Professional |
| vibe | Casual |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | X-Total-Count | integer | none | |
| 200 | Cache-Control | string | none | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
generateAiContent
Code samples
const inputBody = '{
"type": "CoverLetter",
"context": {
"jobDescription": "We are seeking a Senior Salesforce Architect...",
"companyName": "Acme Corp",
"role": "Senior Technical Architect",
"skills": [
"Apex",
"LWC",
"Integration Architecture"
],
"experienceSummary": "7+ years as Salesforce Architect"
},
"tone": "Professional",
"maxLength": 500
}';
const headers = {
'Content-Type':'application/json',
'Accept':'application/json',
'X-Request-Id':'497f6eca-6276-4993-bfeb-53cbbbba6f08',
'X-API-Version':'v1',
'client_id':'API_KEY',
'client_secret':'API_KEY'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/ai/generate',
{
method: 'POST',
body: inputBody,
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
POST /ai/generate
Generate AI Content (Multi-Cloud Resilience)
Proxies generative AI requests to LLM providers with circuit breaker pattern.
Provider Priority Chain:
- Primary: Salesforce Agentforce (if available)
- Fallback 1: Google Gemini Flash 2.0 (via AWS Lambda)
- Fallback 2: OpenAI GPT-4o-mini (via AWS Lambda)
Circuit Breaker & Limits:
- Rate Limit: 10 requests per minute (User)
- Timeouts: 2 seconds per provider, 5 seconds total max execution.
- Threshold: Circuit opens after 3 consecutive failures.
- Reset: Circuit attempts reset after 30 seconds.
Security:
- API keys for Gemini/OpenAI stored in AWS Secrets Manager
- Never exposed to frontend or Salesforce
- Rotated every 90 days via automated Lambda
Body parameter
{
"type": "CoverLetter",
"context": {
"jobDescription": "We are seeking a Senior Salesforce Architect...",
"companyName": "Acme Corp",
"role": "Senior Technical Architect",
"skills": [
"Apex",
"LWC",
"Integration Architecture"
],
"experienceSummary": "7+ years as Salesforce Architect"
},
"tone": "Professional",
"maxLength": 500
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| X-Request-Id | header | string(uuid) | false | Correlation ID propagated to SAPI. |
| X-API-Version | header | string | true | API Version (e.g., v1). |
| body | body | object | true | none |
| » type | body | string | true | The type of content to generate |
| » context | body | object | true | Contextual data for generation |
| »» jobDescription | body | string | false | Full text of job posting (for cover letters) |
| »» companyName | body | string | false | none |
| »» role | body | string | false | none |
| »» skills | body | [string] | false | Skills to emphasize |
| »» experienceSummary | body | string | false | Brief professional summary |
| » tone | body | string | false | Desired tone of generated content |
| » maxLength | body | integer | false | Maximum character count |
Enumerated Values
| Parameter | Value |
|---|---|
| » type | CoverLetter |
| » type | BioSummary |
| » type | SkillDescription |
| » tone | Professional |
| » tone | Enthusiastic |
| » tone | Technical |
| » tone | Casual |
Example responses
200 Response
{
"content": "Dear Hiring Manager,\n\nI am writing to express my strong interest in the Senior Technical Architect position at Acme Financial...\n",
"provider": "Gemini Flash 2.0",
"model": "gemini-2.0-flash-exp",
"generatedAt": "2019-08-24T14:15:22Z",
"tokensUsed": 487,
"fallbackOccurred": false
}
400 Response
{
"httpStatus": 400,
"errorCode": "BAD_REQUEST",
"message": "Invalid persona value.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
401 Response
{
"httpStatus": 401,
"errorCode": "UNAUTHORIZED",
"message": "Invalid client_id or client_secret",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": false
}
429 Response
{
"httpStatus": 429,
"errorCode": "RATE_LIMIT_EXCEEDED",
"message": "LLM provider quota exceeded. Retry after 60 seconds.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
500 Response
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "Failed to aggregate profile data. Partial SAPI failure.",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {
"failedSapiCalls": [
{
"endpoint": "/experience-skills",
"error": "Connection timeout"
}
]
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "ALL_PROVIDERS_UNAVAILABLE",
"message": "All AI providers currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Successfully generated content | Inline |
| 400 | Bad Request | Invalid request parameters | Error |
| 401 | Unauthorized | Invalid Client Credentials | Error |
| 429 | Too Many Requests | Rate limit exceeded (LLM provider quota) | Error |
| 500 | Internal Server Error | Internal PAPI error or SAPI communication failure | Error |
| 503 | Service Unavailable | All AI providers unavailable | Error |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| » content | string | true | none | The generated text content |
| » provider | string | true | none | LLM provider used |
| » model | string | false | none | Specific model version |
| » generatedAt | string(date-time) | true | none | none |
| » tokensUsed | integer | false | none | Approximate token count (for cost tracking) |
| » fallbackOccurred | boolean | false | none | True if primary provider failed |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | X-AI-Provider | string | Which LLM provider was used | |
| 200 | X-Generation-Time-Ms | integer | Time taken to generate content in milliseconds | |
| 400 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 401 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 429 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 429 | Retry-After | integer | none | |
| 500 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
Monitoring
Health checks and observability
getHealth
Code samples
const headers = {
'Accept':'application/json'
};
fetch('https://api.portfolio.ryanbumstead.com/papi/health',
{
method: 'GET',
headers: headers
})
.then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});
GET /health
PAPI Health Check
Performs a shallow health check (runtime only). Does not validate SAPI connectivity.
Example responses
200 Response
{
"status": "UP",
"timestamp": "2019-08-24T14:15:22Z",
"dependencies": {
"sapi": "not_checked"
}
}
503 Response
{
"httpStatus": 503,
"errorCode": "SERVICE_UNAVAILABLE",
"message": "Downstream SAPI is currently unavailable",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | Service is healthy | HealthStatus |
| 503 | Service Unavailable | PAPI or downstream SAPI is unavailable | Error |
Response Headers
| Status | Header | Type | Format | Description |
|---|---|---|---|---|
| 200 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 200 | Cache-Control | string | none | |
| 503 | X-Request-Id | string | uuid | Correlation ID for distributed tracing |
| 503 | Retry-After | integer | Seconds until service may be available |
Schemas
Error
{
"httpStatus": 500,
"errorCode": "INTERNAL_SERVER_ERROR",
"message": "An unexpected error occurred",
"correlationId": "123e4567-e89b-12d3-a456-426614174000",
"retryable": true,
"details": {}
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| httpStatus | integer | true | none | none |
| errorCode | string | true | none | none |
| message | string | true | none | none |
| correlationId | string(uuid) | true | none | none |
| retryable | boolean | true | none | Indicates if the client should retry the request |
| details | object | false | none | Additional error context (optional) |
HealthStatus
{
"status": "UP",
"timestamp": "2019-08-24T14:15:22Z",
"dependencies": {
"sapi": "not_checked"
}
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| status | string | false | none | none |
| timestamp | string(date-time) | false | none | none |
| dependencies | object | false | none | none |
| » sapi | string | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| status | UP |
| status | DOWN |
| status | DEGRADED |
FullPortfolioPayload
{
"config": {
"ownerEmail": "bumsteadryan@gmail.com",
"ownerPhone": "+1 555-0199",
"linkedInUrl": "https://linkedin.com/in/ryanbumstead",
"calendlyUrl": "https://calendly.com/ryanbumstead",
"githubUrl": "https://github.com/ryanbumstead",
"trailheadUrl": "https://trailblazer.me/id/ryanbumstead",
"personalWebsiteUrl": "https://ryanbumstead.com",
"careerObjective": "Driving digital transformation through architecture.",
"jiraProjectKey": "SPAP",
"gitHubRepoPath": "rdbumstead/salesforce-portfolio"
},
"contactInfo": {
"id": "0035e00000B2O3DAAV",
"fullName": "Ryan Bumstead",
"email": "ryan@ryanbumstead.com",
"phone": "+1 555-0199",
"title": "Platform Architect",
"linkedIn": "https://linkedin.com/in/ryanbumstead",
"github": "https://github.com/ryanbumstead",
"trailhead": "https://trailblazer.me/id/ryanbumstead",
"portfolioUrl": "https://ryanbumstead.com",
"bio": "Specializing in API-led connectivity..."
},
"summary": "7+ years of experience as a Salesforce Platform Architect",
"skills": [
{
"id": "a075e00000B2O3DAAV",
"name": "Apex",
"displayName": "Salesforce Apex",
"category": "Backend",
"proficiency": 5,
"iconName": "utility:code",
"colorHex": "#0070d2",
"categoryOrder": 10
}
],
"experience": [
{
"id": "a025e00000B2O3DAAV",
"employer": "Salesforce",
"role": "Senior Technical Architect",
"dateRange": "Jan 2023 - Present",
"isCurrent": true,
"isRemote": true,
"skillsUsed": [
"LWC"
],
"highlights": [
"Implemented CI/CD pipelines using GitHub Actions"
]
}
],
"projects": [
{
"id": "a015e00000B2O3DAAV",
"title": "Portfolio Site",
"challenge": "Display skills dynamically to recruiters",
"solution": "Built on LWR with SAPI/PAPI architecture",
"businessValue": "Increased interview rate by 40%",
"status": "Live – In Production",
"completionDate": "2025-12-01",
"heroImageUrl": "https://assets.portfolio.com/hero.png",
"liveUrl": "https://portfolio.ryanbumstead.com",
"repositoryUrl": "https://github.com/ryanbumstead/portfolio",
"technologies": [
"Apex"
],
"pillarLabel": "Pillar A: Business Architecture",
"assets": [
{
"type": "Image",
"url": "https://assets.portfolio.com/diagram.png",
"caption": "System Architecture Diagram"
}
]
}
],
"certifications": [
{
"id": "a105e00000B2O3DAAV",
"name": "Certified Application Architect",
"issuer": "Salesforce",
"dateEarned": "2024-05-15",
"skillsUsed": [
"Security"
]
}
],
"education": [
{
"id": "a115e00000B2O3DAAV",
"school": "Creighton University",
"degree": "B.S. Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2018",
"gpa": 3.8
}
],
"testimonials": [
{
"id": "a055e00000B2O3DAAV",
"author": "Jane Doe",
"title": "VP of Engineering",
"relationship": "Manager",
"quote": "Ryan is a beast at architecture",
"vibe": "Professional",
"avatarUrl": "https://linkedin.com/in/janedoe/photo"
}
],
"integrityNote": "string"
}
The master payload for initial app load
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| config | PortfolioConfig | true | none | none |
| contactInfo | ContactDetail | true | none | Simplified contact information for the header |
| summary | string | false | none | Auto-generated professional summary |
| skills | [SkillSummary] | true | none | [Lightweight skill object for list views] |
| experience | [EnrichedExperience] | true | none | [Work Experience enriched with related Skills and Highlights] |
| projects | [EnrichedProject] | true | none | [Project enriched with Skills and Assets] |
| certifications | [EnrichedCertification] | true | none | [Certification with associated skills] |
| education | [SimpleEducation] | true | none | [Educational background] |
| testimonials | [EnrichedTestimonial] | true | none | none |
| integrityNote | string¦null | false | none | Debug info if partial data returned (e.g. ‘Certifications Service Unavailable’) |
ProfileSummary
{
"contactInfo": {
"id": "0035e00000B2O3DAAV",
"fullName": "Ryan Bumstead",
"email": "ryan@ryanbumstead.com",
"phone": "+1 555-0199",
"title": "Platform Architect",
"linkedIn": "https://linkedin.com/in/ryanbumstead",
"github": "https://github.com/ryanbumstead",
"trailhead": "https://trailblazer.me/id/ryanbumstead",
"portfolioUrl": "https://ryanbumstead.com",
"bio": "Specializing in API-led connectivity..."
},
"summary": "7+ years of experience as a Salesforce Platform Architect",
"skills": [
{
"id": "a075e00000B2O3DAAV",
"name": "Apex",
"displayName": "Salesforce Apex",
"category": "Backend",
"proficiency": 5,
"iconName": "utility:code",
"colorHex": "#0070d2",
"categoryOrder": 10
}
],
"experience": [
{
"id": "a025e00000B2O3DAAV",
"employer": "Salesforce",
"role": "Senior Technical Architect",
"dateRange": "Jan 2023 - Present",
"isCurrent": true,
"isRemote": true,
"skillsUsed": [
"LWC"
],
"highlights": [
"Implemented CI/CD pipelines using GitHub Actions"
]
}
],
"certifications": [
{
"id": "a105e00000B2O3DAAV",
"name": "Certified Application Architect",
"issuer": "Salesforce",
"dateEarned": "2024-05-15",
"skillsUsed": [
"Security"
]
}
],
"education": [
{
"id": "a115e00000B2O3DAAV",
"school": "Creighton University",
"degree": "B.S. Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2018",
"gpa": 3.8
}
]
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| contactInfo | ContactDetail | true | none | Simplified contact information for the header |
| summary | string | false | none | Calculated summary based on experience |
| skills | [SkillSummary] | true | none | [Lightweight skill object for list views] |
| experience | [EnrichedExperience] | true | none | [Work Experience enriched with related Skills and Highlights] |
| certifications | [EnrichedCertification] | true | none | [Certification with associated skills] |
| education | [SimpleEducation] | true | none | [Educational background] |
EnrichedExperience
{
"id": "a025e00000B2O3DAAV",
"employer": "Salesforce",
"role": "Senior Technical Architect",
"dateRange": "Jan 2023 - Present",
"isCurrent": true,
"isRemote": true,
"skillsUsed": [
"LWC"
],
"highlights": [
"Implemented CI/CD pipelines using GitHub Actions"
]
}
Work Experience enriched with related Skills and Highlights
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | Salesforce Record ID (18-char) |
| employer | string | true | none | none |
| role | string¦null | false | none | none |
| dateRange | string | true | none | Formatted as “MMM YYYY - MMM YYYY” or “MMM YYYY - Present” |
| isCurrent | boolean¦null | false | none | none |
| isRemote | boolean¦null | false | none | none |
| skillsUsed | [string] | false | none | Skills derived from ExperienceSkill junction |
| highlights | [string] | false | none | Selected bullet points (filtered by persona if applicable) |
EnrichedProject
{
"id": "a015e00000B2O3DAAV",
"title": "Portfolio Site",
"challenge": "Display skills dynamically to recruiters",
"solution": "Built on LWR with SAPI/PAPI architecture",
"businessValue": "Increased interview rate by 40%",
"status": "Live – In Production",
"completionDate": "2025-12-01",
"heroImageUrl": "https://assets.portfolio.com/hero.png",
"liveUrl": "https://portfolio.ryanbumstead.com",
"repositoryUrl": "https://github.com/ryanbumstead/portfolio",
"technologies": [
"Apex"
],
"pillarLabel": "Pillar A: Business Architecture",
"assets": [
{
"type": "Image",
"url": "https://assets.portfolio.com/diagram.png",
"caption": "System Architecture Diagram"
}
]
}
Project enriched with Skills and Assets
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | none |
| title | string¦null | false | none | none |
| challenge | string | false | none | none |
| solution | string | false | none | none |
| businessValue | string | false | none | none |
| status | string¦null | false | none | Project Status (e.g., Live, Archived) |
| completionDate | string(date)¦null | false | none | Mapped from SAPI dateCompleted |
| heroImageUrl | string(uri) | false | none | URL of the main display image. Matches SAPI field name. |
| liveUrl | string(uri) | false | none | none |
| repositoryUrl | string(uri) | false | none | none |
| technologies | [string] | false | none | Skill names from ProjectSkill junction |
| pillarLabel | string¦null | false | none | The strategic pillar and pillar description (e.g. Pillar A: Business Architecture) |
| assets | [object] | false | none | Images, videos, or links related to the project |
| » type | string | true | none | none |
| » url | string(uri) | true | none | none |
| » caption | string | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| type | Image |
| type | Video |
| type | Document |
| type | Link |
EnrichedTestimonial
{
"id": "a055e00000B2O3DAAV",
"author": "Jane Doe",
"title": "VP of Engineering",
"relationship": "Manager",
"quote": "Ryan is a beast at architecture",
"vibe": "Professional",
"avatarUrl": "https://linkedin.com/in/janedoe/photo"
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | none |
| author | string | true | none | none |
| title | string | false | none | none |
| relationship | string | false | none | none |
| quote | string | true | none | none |
| vibe | string | false | none | none |
| avatarUrl | string(uri) | false | none | none |
Enumerated Values
| Property | Value |
|---|---|
| relationship | Manager |
| relationship | Peer |
| relationship | Client |
| relationship | Recruiter |
| relationship | Fan |
| vibe | Professional |
| vibe | Casual |
PortfolioConfig
{
"ownerEmail": "bumsteadryan@gmail.com",
"ownerPhone": "+1 555-0199",
"linkedInUrl": "https://linkedin.com/in/ryanbumstead",
"calendlyUrl": "https://calendly.com/ryanbumstead",
"githubUrl": "https://github.com/ryanbumstead",
"trailheadUrl": "https://trailblazer.me/id/ryanbumstead",
"personalWebsiteUrl": "https://ryanbumstead.com",
"careerObjective": "Driving digital transformation through architecture.",
"jiraProjectKey": "SPAP",
"gitHubRepoPath": "rdbumstead/salesforce-portfolio"
}
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| ownerEmail | string(email) | true | none | none |
| ownerPhone | string | false | none | none |
| linkedInUrl | string(uri) | false | none | none |
| calendlyUrl | string(uri) | false | none | none |
| githubUrl | string(uri) | false | none | none |
| trailheadUrl | string(uri) | false | none | none |
| personalWebsiteUrl | string(uri) | false | none | none |
| careerObjective | string | false | none | Short professional bio/objective |
| jiraProjectKey | string | false | none | Key for Jira integration |
| gitHubRepoPath | string | false | none | GitHub Owner/Repo path |
ContactDetail
{
"id": "0035e00000B2O3DAAV",
"fullName": "Ryan Bumstead",
"email": "ryan@ryanbumstead.com",
"phone": "+1 555-0199",
"title": "Platform Architect",
"linkedIn": "https://linkedin.com/in/ryanbumstead",
"github": "https://github.com/ryanbumstead",
"trailhead": "https://trailblazer.me/id/ryanbumstead",
"portfolioUrl": "https://ryanbumstead.com",
"bio": "Specializing in API-led connectivity..."
}
Simplified contact information for the header
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | false | none | none |
| fullName | string | true | none | none |
| string(email) | true | none | none | |
| phone | string | false | none | none |
| title | string¦null | false | none | none |
| string(uri) | false | none | none | |
| github | string(uri) | false | none | none |
| trailhead | string(uri) | false | none | none |
| portfolioUrl | string(uri) | false | none | none |
| bio | string | false | none | The ‘Career Objective’ from Salesforce |
SkillSummary
{
"id": "a075e00000B2O3DAAV",
"name": "Apex",
"displayName": "Salesforce Apex",
"category": "Backend",
"proficiency": 5,
"iconName": "utility:code",
"colorHex": "#0070d2",
"categoryOrder": 10
}
Lightweight skill object for list views
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | none |
| name | string | true | none | none |
| displayName | string | false | none | Prefer this over ‘name’ for UI rendering if present |
| category | string | true | none | none |
| proficiency | number | true | none | 1-5 score |
| iconName | string | false | none | SLDS Icon reference |
| colorHex | string | false | none | Brand color for the category |
| categoryOrder | number | false | none | Order to display the category in the UI |
EnrichedCertification
{
"id": "a105e00000B2O3DAAV",
"name": "Certified Application Architect",
"issuer": "Salesforce",
"dateEarned": "2024-05-15",
"skillsUsed": [
"Security"
]
}
Certification with associated skills
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | none |
| name | string | true | none | none |
| issuer | string | true | none | none |
| dateEarned | string(date) | true | none | none |
| skillsUsed | [string] | false | none | Derived from CertificationSkill junction |
SimpleEducation
{
"id": "a115e00000B2O3DAAV",
"school": "Creighton University",
"degree": "B.S. Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2018",
"gpa": 3.8
}
Educational background
Properties
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
| id | string | true | none | none |
| school | string | true | none | none |
| degree | string | true | none | none |
| fieldOfStudy | string | false | none | none |
| year | string | true | none | Graduation Year derived from Graduation Date |
| gpa | number¦null | false | none | none |