Stage APIstage.ma ↗
Access internship listings and details from Stage.ma via 2 endpoints. Search by city, specialty, remote type, and salary. Retrieve full posting details by slug.
What is the Stage API?
The Stage.ma API exposes 2 endpoints for accessing internship listings from Morocco's internship platform. The search_internships endpoint returns paginated results — 10 per page — filterable by city, specialty, remote type, and salary status, while get_internship delivers full posting details including duration, positions available, and company name for any specific listing.
curl -X GET 'https://api.parse.bot/scraper/f6d6378b-fce9-41d8-86e6-6cd0de4e0708/search_internships?page=1&salary=true&search=marketing&location=5&specialty=8&remote_type=onsite' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace stage-ma-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Stage.ma SDK — search and inspect Moroccan internships."""
from parse_apis.stage_ma_api import StageMa, Specialty, RemoteType, InternshipNotFound
client = StageMa()
# Search internships filtered by specialty (Marketing)
for internship in client.internship_summaries.search(specialty=Specialty.MARKETING, limit=3):
print(internship.title, "|", internship.location, "|", internship.duration)
# Drill into the first IT internship for full details
it_result = client.internship_summaries.search(
specialty=Specialty.INFORMATIQUE, limit=1
).first()
if it_result:
detail = it_result.details()
print(detail.title, detail.city, detail.salary, detail.availability)
print(detail.description[:120])
# Search with remote type filter and paid only
for internship in client.internship_summaries.search(
remote_type=RemoteType.ONSITE, salary="true", limit=3
):
print(internship.title, internship.company, internship.tags)
# Typed error handling: attempt to get a non-existent internship
if it_result:
try:
detail = it_result.details()
print(detail.title, detail.published_date)
except InternshipNotFound as exc:
print(f"Not found: {exc.slug}")
print("exercised: search (specialty/remote_type/salary filters) / details / error handling")
Search internship listings on Stage.ma with optional filters for specialty, location, remote type, and salary. Returns paginated results with 10 items per page. Each result includes title, company, location, duration, start date, and tags.
| Param | Type | Description |
|---|---|---|
| page | integer | Page number for pagination. |
| salary | string | Set to 'true' to filter only paid internships, 'false' or omit for all. |
| search | string | Free-text search query to filter internships by title or keywords. |
| location | string | City ID to filter by location. |
| specialty | string | Specialty ID to filter by field of study. |
| remote_type | string | Presence type filter. |
{
"type": "object",
"fields": {
"count": "integer",
"internships": "array of internship summary objects",
"current_page": "integer",
"has_next_page": "boolean"
},
"sample": {
"data": {
"count": 10,
"internships": [
{
"id": "9312",
"slug": "9312-offre-de-stage-photographer-videographer",
"tags": [
"Marketing",
"Stage Opérationnel"
],
"title": "Offre de Stage – Photographer / Videographer",
"company": "Billionnaire Invest",
"duration": "1 - 3 mois",
"location": "Casablanca",
"positions": 2,
"start_date": "19/04/2026",
"company_url": "https://www.stage.ma/organismes/16972-billionnaire-invest",
"free_submissions_left": 15
}
],
"current_page": 1,
"has_next_page": true
},
"status": "success"
}
}About the Stage API
Search Internship Listings
The search_internships endpoint queries the Stage.ma catalog with several optional filters: search accepts free-text keywords, location takes a city ID, specialty takes a field-of-study ID, remote_type filters by presence format, and salary set to 'true' restricts results to paid internships only. Each response includes a count of total matches, a has_next_page boolean for pagination control, and an internships array of summary objects — each containing title, company, location, duration, start date, and tags.
Internship Detail
The get_internship endpoint accepts a slug in the format {id}-{title-slug} (for example, 9310-consultant-junior-data), which can be extracted directly from search_internships results. The response returns 10 fields covering the full posting: title, company, city, specialty, duration, start_date, salary, presence, positions, and status. The status field indicates whether the listing is currently active or closed.
Pagination and Filtering
Results are paged at 10 items per response. Pass the page integer parameter to walk through result sets. Filter combinations — such as a search query paired with a location ID and salary=true — are all supported in a single request. City and specialty IDs follow Stage.ma's internal taxonomy, so you may need to inspect a few search results to identify the correct ID values for a given filter.
The Stage API is a managed, monitored endpoint for stage.ma — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when stage.ma changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official stage.ma API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Aggregate paid internship openings in Casablanca or Rabat using location and salary filters
- Build an internship recommendation tool that matches students to listings by specialty ID
- Monitor new listings in a specific field by polling search_internships with a specialty filter
- Extract company names and positions counts from get_internship to analyze hiring volume by firm
- Track internship start dates across listings to surface seasonality trends in the Moroccan market
- Filter remote or hybrid internships using the remote_type parameter for distributed-work dashboards
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.